package com.easyliving.app.lib.net;


import androidx.annotation.NonNull;

import java.io.File;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

import kotlin.jvm.Throws;
import okhttp3.Cache;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * Retrofit工厂类
 * @author chiboo
 */
public class RetrofitFactory {
    private volatile static String mBaseUrl;
    private volatile static Map<String, String> mHeaderData;
    private volatile static Retrofit mRetrofit;

    @NonNull
    public static Retrofit getRetrofit() throws Exception {
        if (mBaseUrl == null) {
            mRetrofit = null;
            throw new Exception("mBaseUrl cannot be null!");
        }
        if (mRetrofit == null) {
            synchronized (RetrofitFactory.class) {
                if (mRetrofit == null) {
                    mRetrofit = buildRetrofit(mHeaderData, mBaseUrl);
                }
            }
        }
        return mRetrofit;
    }

    public static void init(@NonNull String serverUrl) {
        mBaseUrl = serverUrl;
    }
    public static void init(@NonNull String serverUrl, Map<String, String> headers) {
        mBaseUrl = serverUrl;
        mHeaderData = headers;
    }

    public static void rebuild() {
        Objects.requireNonNull(mBaseUrl, "baseUrl cannot be null!");
        synchronized (RetrofitFactory.class) {
            mRetrofit = buildRetrofit(mHeaderData, mBaseUrl);
        }
    }

    private static final Interceptor cacheControlInterceptor = new Interceptor() {
        @Override
        public Response intercept(Chain chain) throws IOException {
            Request request = chain.request();

            Response originalResponse = chain.proceed(request);
            // 有网络时 设置缓存为默认值
            String cacheControl = request.cacheControl().toString();
            return originalResponse.newBuilder()
                    .header("Cache-Control", cacheControl)
                    .removeHeader("Pragma") // 清除头信息，因为服务器如果不支持，会返回一些干扰信息，不清除下面无法生效
                    .build();
        }
    };

    private static class HeaderInterceptor implements Interceptor {
        private Map<String, String> headerData;

        public HeaderInterceptor(Map<String, String> headerData) {
            this.headerData = headerData;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request.Builder builder = chain.request().newBuilder();
            for (Map.Entry<String, String> entry : headerData.entrySet()) {
                builder.addHeader(entry.getKey(), entry.getValue());
            }
            return chain.proceed(builder.build());
        }
    }

    // 指定缓存路径,缓存大小 50Mb
    private static Cache cache = new Cache(new File("./", "HttpCache"),
            1024 * 1024 * 50);

    private static Retrofit buildRetrofit(Map<String, String> headerData, String serverUrl) {
        OkHttpClient.Builder builder = new OkHttpClient.Builder()
                .cache(cache)
                .addInterceptor(cacheControlInterceptor)
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(15, TimeUnit.SECONDS)
                .writeTimeout(15, TimeUnit.SECONDS)
                .retryOnConnectionFailure(true);
        if (headerData != null) {
            HeaderInterceptor headerInterceptor = new HeaderInterceptor(headerData);
            builder.addInterceptor(headerInterceptor);
        }
        Retrofit retrofit = new Retrofit.Builder()
                .baseUrl(serverUrl)
                .client(builder.build())
                .addConverterFactory(GsonConverterFactory.create())
                //指定为LiveData数据适配
                .addCallAdapterFactory(LiveDataCallAdapterFactory.create())
                .build();
        return retrofit;
    }
}
